﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 数据结构课设_电文的编码与译码_CSharp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void buttonOpenFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = Application.StartupPath;
            openFileDialog.Filter = null;
            openFileDialog.RestoreDirectory = true;
            if (openFileDialog.ShowDialog() == DialogResult.OK) {
                textBox_openFile.Text = openFileDialog.FileName;
            }
        }

        private void buttoSaveFile_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.FolderBrowserDialog folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
            folderBrowserDialog.Description = "请选择编码(译码)后的文件保存路径";
            if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                textBox_saveFile.Text = folderBrowserDialog.SelectedPath;
            }
        }

        private void huffmanEncode(String openFileName, String saveFileName)
        {
            //打开要加密的文件
            FileStream openFileSream = new FileStream(openFileName, FileMode.Open , FileAccess.Read);
            long int_fileSreamLength = openFileSream.Length;
            if (int_fileSreamLength == 0)
            {
                MessageBox.Show("加密文件为空!");
                return;
            }
            //打开要保存的文件
            FileStream saveFileSream = new FileStream(saveFileName+"save.txt", FileMode.Create, FileAccess.Write);
            //临时保存读取到的字节编码
            int int_readTypes;
            //用于存储字节编码,统计出现的次数
            Dictionary<char, ulong> tempSaveDictionary = new Dictionary<char, ulong>();
            int int_count = 0;
            for (int i=0; i< int_fileSreamLength; i++) {
                Console.WriteLine("统计编码次数:"+((i * 1.0 )/ (int_fileSreamLength*1.0))*100+"%");
                int_readTypes = openFileSream.ReadByte();
                if (tempSaveDictionary.ContainsKey((char)int_readTypes))
                {
                    tempSaveDictionary[(char)int_readTypes]++;
                }
                else
                {
                    tempSaveDictionary.Add((char)int_readTypes, 1);
                    int_count++;
                }
            }
            //记录编码原始数据
            Link link_source_data = new Link();
            //遍历输出
            //string str_show="";
            foreach (KeyValuePair<char, ulong> kvp in tempSaveDictionary)
            {
                //升序插入
                link_source_data.InsertAscending(kvp.Value, kvp.Key);
                //str_show += ((int)(kvp.Key)).ToString("x8") + " " + kvp.Value + "\n";
            }
            StreamWriter streamWriter = new StreamWriter(saveFileSream);
            //streamWriter.Write(str_show + "\n" + "\n" + "\n");
            link_source_data.MoveFrist();
            
            do
            {
                //Console.WriteLine(link_code.GetCurrentKey());
                streamWriter.Write(((int)(link_source_data.GetCurrentKey())).ToString("x2") + " " + (link_source_data.GetCurrentWeight()).ToString() + "\n");
            } while (link_source_data.MoveNext());
            
            //计算哈夫曼编码
            Huffman huffman = new Huffman(link_source_data.GetNode());
            huffman.CreateHuffmanTree();
            huffman.CreateHuffmanDictionary();
            Node huffmandictionary = huffman.getHuffmanDictionary();

            streamWriter.Write("\n\n\n\n\n\n");
            do
            {
                //Console.WriteLine(link_code.GetCurrentKey());
                streamWriter.Write(((int)(huffmandictionary.Key)).ToString("x2") + " " + (huffmandictionary.Code) + "\n");
                huffmandictionary = huffmandictionary.Next;
            } while (huffmandictionary.Next!=null);

            openFileSream.Close();
            streamWriter.Close();
            //MessageBox.Show(str_show);
        }

        private void buttonEncode_Click(object sender, EventArgs e)
        {
            huffmanEncode(textBox_openFile.Text, textBox_saveFile.Text);
        }
    }
}
